/**************************************************************************** 
* 
* Copyright (c) 2023  C*Core -   All Rights Reserved  
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* 
* PROJECT     : CCFC2011BC           
* DESCRIPTION : pit demo code
* HISTORY     : Initial version. 
* @file     pit_demo.c
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
* 
*****************************************************************************/

#include "pit_demo.h"
#include "led_hw.h"
#include "intc_lld.h"
#include "stm_lld.h"
#include "adc_lld.h"

static uint32_t t_time1 = 0u;
static uint32_t t_loop = 0u;

static void PIT_Callback0(void);
static void PIT_Callback1(void);
static void PIT_Callback2(void);
static void PIT_Callback3(void);
static void PIT_Callback4(void);
static void PIT_Callback5(void);
static void PIT_Callback6(void);
static void PIT_Callback7(void);


/*******************************************************************************
 * @brief      Callback function for PIT Channel 0
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback0(void)
{
    (void)PSPRINTF("PIT Channel 0 expired!\r\n");
    LED_Toggle(LED1);
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 1
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback1(void)
{
    (void)PSPRINTF("PIT Channel 1 expired!\r\n");
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 2
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback2(void)
{
#if !PIT_CASE7
    (void)PSPRINTF("PIT Channel 2 expired!\r\n");
#endif
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 3
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback3(void)
{
    (void)PSPRINTF("PIT Channel 3 expired!\r\n");
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 4
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback4(void)
{
    (void)PSPRINTF("PIT Channel 4 expired!\r\n");
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 5
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback5(void)
{
    (void)PSPRINTF("PIT Channel 5 expired!\r\n");
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 6
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback6(void)
{
#if !PIT_CASE4
    (void)PSPRINTF("PIT Channel 6 expired!\r\n");
#else
    t_time1 = STM_LLD_GetCounter(&STMD);
    t_loop++;
#endif
}

/*******************************************************************************
 * @brief      Callback function for PIT Channel 7
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void PIT_Callback7(void)
{
#if !PIT_CASE5
    PSPRINTF("PIT Channel 7 expired!\r\n");
#else
    LED_Toggle(LED1);
#endif
}

/* 
 * @brief   PIT configuration structure
 * @param  Channel enable or disable 
 * @param  loadvalue for channel  
 * @param  Channel callback function 
 */
static PIT_CH_Config pit_config[PIT_CHANNELS] ={
    {FALSE, 64000000, PIT_Callback0},
    {FALSE, 64000000, PIT_Callback1},
    {FALSE, 64000000, PIT_Callback2},
    {FALSE, 64000000, PIT_Callback3},
    {FALSE, 64000000, PIT_Callback4},
    {FALSE, 64000000, PIT_Callback5},
    {FALSE, 64000000, PIT_Callback6},
    {FALSE, 64000000, PIT_Callback7}
};

/*******************************************************************************
 * @brief      PIT single channel test
 * @param[in]  channel      number of channel
 * @param[out] time     value of start time
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint32_t PIT_Test_Case1(uint32_t channel, uint32_t t_time) /* PRQA S 3219*/
{
    (void)PSPRINTF("\n PIT_Test_Case1 Start!\n");
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    /* Activate and configure PIT configured channel,Enable */
    PIT_LLD_ChannelConf(&PITD, channel, t_time);
    delayms(2000);
    delayms(2000);
    delayms(2000);
    PIT_LLD_DeInit(&PITD);
    (void)PSPRINTF("\n PIT_Test_Case1 End!\n");
    return 0;
}

/*******************************************************************************
 * @brief      PIT_Test_Case2
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint32_t PIT_Test_Case2(void) /* PRQA S 3219*/
{
    (void)PSPRINTF("\n PIT_Test_Case2 Start!\n");
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    /* Activate and configure PIT configured channel0,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL0, 64000000u);
    /* Activate and configure PIT configured channel1,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL1, 64000000u);
    /* Activate and configure PIT configured channel2,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL2, 64000000u);
    /* Activate and configure PIT configured channel3,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL3, 64000000u);
    /* Activate and configure PIT configured channel4,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL4, 64000000u);
    /* Activate and configure PIT configured channel5,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL5, 64000000u);
    /* Activate and configure PIT configured channel6,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL6, 64000000u);
    /* Activate and configure PIT configured channel7,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL7, 64000000u);
    delayms(2000);
    delayms(2000);
    delayms(2000);
    PIT_LLD_DeInit(&PITD);
    (void)PSPRINTF("\n PIT_Test_Case2 End!\n");
    return 0;
}

/*******************************************************************************
 * @brief      PIT_Test_Case3 : PIT api test
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint32_t PIT_Test_Case3(void) /* PRQA S 3219*/
{
    uint32_t t_loadvalue;
    uint32_t t_currentvalue;
    uint32_t t_interruptstate;
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    (void)PSPRINTF("\n PIT_Test_Case3 Start!\n");
    /* Activate and configure PIT configured channel7,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL7, 64000000u);
    delayms(5000);
    /* Close channel */
    PIT_LLD_ChannelStop((uint32_t)CHANNEL7);
    /* Get CHANNEL7 value of start time */
    t_loadvalue = PIT_LLD_GetLoadValue((uint32_t)CHANNEL7);
    /* Get CHANNEL7 current counter value */
    t_currentvalue = PIT_LLD_GetCurrentValue((uint32_t)CHANNEL7);
    /* Get CHANNEL7 interrupt flag state */
    t_interruptstate = PIT_LLD_GetChannelInterruptState((uint32_t)CHANNEL7);
    (void)PSPRINTF("loadvalue = %d, currentvalue = %d, interruptstate = %d", t_loadvalue, t_currentvalue, t_interruptstate);
    delayms(5000);
    /* Reset loadvalue */
    PIT_LLD_SetLoadValue((uint32_t)CHANNEL7, 32000000u);
    /* Restart channel */
    PIT_LLD_ChannelStart((uint32_t)CHANNEL7);
    delayms(1000);
    /* Get CHANNEL7 value of start time */
    t_loadvalue = PIT_LLD_GetLoadValue((uint32_t)CHANNEL7);
    /* Get CHANNEL7 current counter value */
    t_currentvalue = PIT_LLD_GetCurrentValue((uint32_t)CHANNEL7);
    /* Get CHANNEL7 interrupt flag state */
    t_interruptstate = PIT_LLD_GetChannelInterruptState((uint32_t)CHANNEL7);
    (void)PSPRINTF("loadvalue = %d, currentvalue = %d, interruptstate = %d", t_loadvalue, t_currentvalue, t_interruptstate);
    delayms(5000);
    /* Close module */
    PIT_LLD_ModuleDisable();
    (void)PSPRINTF("restart module\r\n");
    delayms(5000);
    /* Restart module */
    PIT_LLD_ModuleEnable();
    delayms(2000);
    delayms(2000);
    PIT_LLD_DeInit(&PITD);
    (void)PSPRINTF("\n PIT_Test_Case3 End!\n");
    return 0;
}

/*******************************************************************************
 * @brief      PIT_Test_Case4: use STM to verify PIT accuracy
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint8_t PIT_Test_Case4(void)
{
    static uint32_t t_time2;
    /* Initialize SWT Delay function */
    STM_LLD_DelayInit();
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    (void)PSPRINTF("\n PIT_Test_Case4 Start!\n");
    /* Activate and configure PIT configured channel6,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL6, 128000000u);
    /* Get difference between two PIT interrupt */
    while (1)
    {
        if (t_loop == 1u)
        {
            t_time2 = t_time1;
        }
        if (t_loop == 2u)
        {
            t_time2 = t_time1 - t_time2;
            t_loop = 0;
            break;
        }
    }
    (void)PSPRINTF("%d\n", t_time2);
    (void)PSPRINTF("\n PIT_Test_Case4 End!\n");
    /* PIT count for 2s , STM should be 2s */
    if ( t_time2 == 2000000u)
        {
            return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/*******************************************************************************
 * @brief      PIT_Test_Case5: use IO to verify PIT accuracy
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint32_t PIT_Test_Case5(void) /* PRQA S 3219*/
{
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    (void)PSPRINTF("\n PIT_Test_Case5 Start!\n");
    /* Activate and configure PIT configured channel6,Enable 
     * in case 5 , IO toggle when PIT generates interrupt*/
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL7, 64000000u);
    delayms(2000u);
    delayms(2000u);
    delayms(2000u);
    PIT_LLD_DeInit(&PITD);
    (void)PSPRINTF("\n PIT_Test_Case5 End!\n");
    return 0;
}

/*******************************************************************************
 * @brief      PIT_Test_Case6: PIT trigger CTU then CTU trigger AD
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint32_t PIT_Test_Case6(void) /* PRQA S 3219*/
{
    uint16_t Result0 = 0u;
    uint16_t ResultInMv0 = 0u;
    uint32_t i = 0u;
    /* CTU[55] means PIT as trigger source
     * 0 means ADC0_CHANNEL0 */
    CTU.EVTCFGR[55].B.CHANNEL_VALUE = 0u;
    /* CTU[55] means PIT as trigger source enable*/
    CTU.EVTCFGR[55].B.TM = 1u;
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    (void)PSPRINTF("\n PIT_Test_Case6 Start!\n");
    /* Activate and configure PIT configured channel7,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL7, 64000000u);
    /* When PIT time_out ,PIT channel7 trigger CTU/ADC/DMA instead of generating interrupt */
    PITD.pit_tagp->CH[CHANNEL7].TCTRL.R = 1U;
    /* Initialize port PB4 for ADC0_CH0 or ADC1_CH0 */
    SIUL_Init_ADC((uint8_t)ADC0_CH0_PCR);
    /* Enables converted data to be overwritten by a new conversion  */
    ADC_0.MCR.R = 0u;
    ADC_0.MCR.R |= (uint32_t)MCR_OWREN_EN;
    /* Set ADC0 sample and convert time */
    ADC_0.CTR0.R = (uint32_t)CTR_INPCMP_2|(uint32_t)CTR_INPSAMP_255;
    /* Data is a result of CTU conversion mode */
    ADC_0.CDR[0].B.RESULT = 2u;
    /* ADC0  CTU mode enable*/
    ADC_0.MCR.B.CTUEN = 1;
    while ( i < 5u)
    {
        /* Wait for CTU convertion ending */
        while ((ADC_0.ISR.B.EOCTU != 1u))
        {}
        /* Get status of ADC0 */
        Result0 = (uint16_t)ADC_0_Receive((uint8_t)0);
        ResultInMv0 = Result0*5000u/0x3FFu;
        (void)PSPRINTF("%d\r\n", ResultInMv0);
        delayms(500);
        i++;
    }
    PIT_LLD_DeInit(&PITD);
    (void)PSPRINTF("\n PIT_Test_Case6 End!\n");
    return 0;
}

/*******************************************************************************
 * @brief      PIT_Test_Case7: PIT trigger ADC
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static uint32_t PIT_Test_Case7(void) /* PRQA S 3219*/
{
    uint16_t Result1 = 0u;
    uint16_t ResultInMv1 = 0u;
    uint32_t i = 0u;
    /* Initialize PIT driver */
    PIT_LLD_Init(&PITD, pit_config);
    (void)PSPRINTF("\n PIT_Test_Case7 Start!\n");
    /* When PIT time_out ,PIT channel2 trigger CTU/ADC/DMA instead of generating interrupt */
    PITD.pit_tagp->CH[CHANNEL2].TCTRL.R = 1U;
    /* Activate and configure PIT configured channel2,Enable */
    PIT_LLD_ChannelConf(&PITD, (uint32_t)CHANNEL2, 64000000u);
    /* Initialize port PB4 for ADC0_CH0 or ADC1_CH0 */
    SIUL_Init_ADC((uint8_t)ADC0_CH0_PCR);    /* PB4 : ADC0_CH0,  ADC1_CH0  */
    /* Enables converted data to be overwritten by a new conversion  */
    ADC_0.MCR.R = 0u;
    ADC_0.MCR.R |= (uint32_t)MCR_OWREN_EN;
    /* Set ADC0 sample and convert time */
    ADC_0.CTR0.R = (uint32_t)CTR_INPCMP_2|(uint32_t)CTR_INPSAMP_255;
    /* Enable ADC0_CHANNEL0 in inject mode*/
    ADC_0.JCMR0.R = 0x00000001U;
    /* Data is a result of inject conversion mode */
    ADC_0.CDR[0].B.RESULT = 0x01u;
    /* ADC0 inject mode enable */
    ADC_0.MCR.B.JTRGEN = 1u;
    while ( i< 5u)
    {
        /* Wait for inject convertion ending */
        while ((ADC_0.ISR.B.JEOC != 1u))
        {}
        /* Get status of ADC0 */
        Result1 = (uint16_t)ADC_0_Receive((uint8_t)0);
        ResultInMv1 = Result1*5000u/0x3FFu;
        (void)PSPRINTF("%d\r\n", ResultInMv1);
        delayms(500u);
        i++;
    }
    (void)PSPRINTF("\n PIT_Test_Case7 End!\n");
    return 0;
}

/*******************************************************************************
 * @brief      PIT_TEST_Demo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void PIT_TEST_Demo(void)
{
    /* Set the current priority */
    INTC_CPR_Init((uint8_t)CPR_PRI_0);
    (void)PSPRINTF("\r\nTest START !\r\n");
    PIT_LLD_FreezeMode(FREEZE_MODE_OFF);
    /* Function:  single channel open  */
#if PIT_CASE1
    (void)PIT_Test_Case1((uint32_t)CHANNEL0, 64000000u);
#endif

    /* Function:  all channel open  */
#if PIT_CASE2
    (void)PIT_Test_Case2();
#endif

    /* Function:  pit API test  */
#if PIT_CASE3
    (void)PIT_Test_Case3();
#endif

    /* Function:  use STM to verify PIT accuracy  */
#if PIT_CASE4
    if (PIT_Test_Case4() == TRUE)
    {
        LED_Set(LED1, LED_ON);
    }
#endif
    /* Function:  use IO to verify PIT accuracy  */
#if PIT_CASE5
    (void)PIT_Test_Case5();
#endif

    /* Function:  CTU trigger ADC,PIT as the trigger source (ADC0_channel0 and only PIT7 can be used as CTU trigger source)  */
#if PIT_CASE6
    (void)PIT_Test_Case6();
#endif

    /* *
     *  Function:  PIT trigger ADC,PIT as the trigger source (ADC0_channel0 and
     * only PIT2(ADC0) and PIT6(ADC1) can be used as direct ADC trigger source)  
     *  */
#if PIT_CASE7
    (void)PIT_Test_Case7();
#endif
}

